/******************************************************************************
 * Copyright (C) 2011 ShenZhen ComTop Information Technology Co.,Ltd
 * All Rights Reserved.
 * 本软件为深圳康拓普开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、
 * 复制、修改或发布本软件.
 *****************************************************************************/

package com.code.common.codegen;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 缺省的掩码处理类。 该类仅将掩码中包含的日期的表达式替换成当前的日期，流水号表达式替换成给定的流水号。 日期掩码格式为：年号(2~4位）+可选的连词符号（1位）+可选的月份(2位)+可选的连词符号（1位）+可选的天(2位） eg:
 * yyyyMMdd yyMMdd yyyy-MM yyyy-dd yyyydd 等都为合法日期。日期掩码将被替换为当前的日期，可以有重复的日期掩码。 序列号的掩码为#(任意位） eg: #(1位序列） ####(4位序列)
 * ########（8位序列）等都为合法的序列掩码。 序列掩码将被替换为给定的数字串。如果序列掩码比给定的数字串长将在前面补0，但是如果短不进行截断。
 * 
 * @author 徐书高
 * @since 1.0
 * @version 2011-08-16 吴宠 修改
 */
public class DefaultMaskProcessor implements MaskProcessor {
    
    /** 匹配单据掩码中的日期所用的表达式 */
    private final static String DATE_EXPRESSION = "(y{2,4})\\-?(M{2})?\\-?(d{2})?";
    
    /** 匹配单据中的流水号所用的表达式 */
    private final static String SEQUENCE_EXPRESSION = "#+";
    
    /**
     * 根据掩码和指定的序列号生成id
     * 
     * @param mask 掩码
     * @param sequence 流水号
     * @return 编码
     */
    public String getCode(String mask, String sequence) {
        
        Pattern objDatePattern = Pattern.compile(DATE_EXPRESSION);
        Pattern objSequencePattern = Pattern.compile(SEQUENCE_EXPRESSION);
        
        // 将日期掩码替换为对应格式的日期
        Matcher dateMatcher = objDatePattern.matcher(mask);
        StringBuffer sbTempResult = new StringBuffer();// 替换日期后的中间结果
        boolean dateFoundResult = dateMatcher.find();
        while (dateFoundResult) {
            String strFoundString = dateMatcher.group();
            SimpleDateFormat dateFormater = new SimpleDateFormat(strFoundString);
            String strReplacement = dateFormater.format(new Date());
            dateMatcher.appendReplacement(sbTempResult, strReplacement);
            dateFoundResult = dateMatcher.find();
        }
        dateMatcher.appendTail(sbTempResult);
        
        // 将中间结果中的序列号掩码替换为流水号
        Matcher objSequenceMatcher = objSequencePattern.matcher(sbTempResult);
        StringBuffer sbResult = new StringBuffer();
        boolean bSeqFoundResult = objSequenceMatcher.find();
        while (bSeqFoundResult) {
            String strFoundString = objSequenceMatcher.group();
            String strSeqReplacement = getFixedSeqence(sequence, strFoundString);
            objSequenceMatcher.appendReplacement(sbResult, strSeqReplacement);
            bSeqFoundResult = objSequenceMatcher.find();
        }
        objSequenceMatcher.appendTail(sbResult);
        
        return sbResult.toString();
    }
    
    /**
     * 根据输入的掩码长度来对给定的序列号进行补零操作。 NOTE: 该方法不对序列掩码是否合法进行验证，并且只补0不截断，<BR>
     * 因此返回的序列号可能比掩码规定的要长。
     * 
     * @param sequenceNum 序列号数字
     * @param sequenceMask 序列号掩码
     * @return 补零后的序列号
     */
    private String getFixedSeqence(String sequenceNum, String sequenceMask) {
        StringBuffer sbResult = new StringBuffer();
        int iSequenceNumLen = sequenceNum.trim().length();
        int iSequenceMaskLen = sequenceMask.length();
        
        // 如果掩码的长度大于给定的序列号的长度就在前面补0
        if (iSequenceMaskLen > iSequenceNumLen) {
            for (int i = 0; i < iSequenceMaskLen - iSequenceNumLen; i++) {
                sbResult.append("0");
            }
        }
        
        sbResult.append(sequenceNum);
        
        return sbResult.toString();
    }
}